import { RouteObject } from "react-router-dom";
import RouteConfigType from "./RouteConfigType";
import React, { Suspense } from "react";
import LoadingComponent from "common/loading/LoadingComponent";
import { MessageInstance } from "antd/es/message/interface";

type RouteItem = {
    path: string,
    key: string,
    mainPath?: boolean,
    children?: RouteItem[],
    skipRender?: boolean,
    index?: boolean
    desc?: string
    pathSuffix?: string
}

/**
 * 路由解析器
 */
export default class RouteResolve {
    private readonly CONFIG_PREFIX: string = "page";
    private readonly CONFIG_SUFFIX: string = "/config.ts";
    // 找到路径中只有一个/的路径,一级路径
    // ^: 匹配字符串的开始位置
    // \/: 匹配一个 / 字符
    // [^\/]+: 匹配除了 / 之外的任意字符，+ 表示至少匹配一个字符
    // $: 匹配字符串的结束位置
    private readonly regexMainPath = /^\/[^\/]+$/;
    private readonly context = require.context("/src/page", true, /\.tsx$/, "lazy");
    private readonly configs = require.context('page', true, /\.(ts)$/, "sync");
    private readonly configKeys = this.configs.keys().filter(c => c.startsWith("page"));
    private routes: RouteObject[] = [];
    private readonly message: MessageInstance ;

    constructor(message: MessageInstance) {
        this.message = message;
        this.init();
    }

    private init = () => {
        const routeInfos = this.parseRouteInfo();
        const mainRoutes = routeInfos.filter(r => r.mainPath);
        const childrenRoutes = routeInfos.filter(r => !r.mainPath).map(this.convertRouteItemToRouteObject);
        this.routes = mainRoutes.map(this.convertRouteItemToRouteObject);
        this.routes.forEach(r => {
            this.findRouteChildren(r, childrenRoutes);
        });
    } ;

    /**
     * 这里只是找到目录的直接子目录
     */
    private findRouteChildren = (parent: RouteObject, routes: RouteObject[]) => {
        if (parent.index) {
            // console.warn("当前路由是索引路由,不需要查找子目录", parent);
            return;
        }
        parent.children = [];
        routes.filter(r => {
            if (r.id?.match(new RegExp("^" + parent.id + "/[a-z-]+$")) !== null) {
                parent.children?.push(r);
                this.findRouteChildren(r, routes);
            }
        });
    } ;

    private convertRouteItemToRouteObject = (routeItem: RouteItem): RouteObject => {
        if (routeItem.index) {
            return {
                id: routeItem.path,
                index: true,
                element: this.lazyLoadComponent(routeItem.key),
            };
        }
        return {
            id: routeItem.path,
            path: routeItem.pathSuffix ? routeItem.path + routeItem.pathSuffix : routeItem.path,
            element: this.lazyLoadComponent(routeItem.key),
        };
    }

    /**
     * 解析路由信息
     * @returns 解析出的路由数组
     */
    public parseRoute = (): RouteObject[] => {
        if (this.routes.length === 0) {
            throw new Error("路由系统路由解析失败");
        }
        return this.routes;
    } ;

    // 解析路由信息
    private parseRouteInfo = (): RouteItem[] => {
        return this.context.keys()
            .filter((item) => item.startsWith("./"))
            .map((item) => {
                let path = item.replace(".", "").replace(new RegExp("/[A-Z][A-Za-z]+.tsx"), "");
                let isConfig: boolean = this.configKeys.includes(this.CONFIG_PREFIX + path + this.CONFIG_SUFFIX);
                let tempRouteItem: RouteItem = {
                    path: path,
                    key: item,
                    mainPath: path.match(this.regexMainPath) !== null,
                };
                if (isConfig) {
                    let routeConfig: RouteConfigType = this.configs(this.CONFIG_PREFIX + path + this.CONFIG_SUFFIX).default;
                    // console.log("找到路由配置文件",path, routeConfig);
                    tempRouteItem.index = routeConfig.index;
                    tempRouteItem.skipRender = routeConfig.isSkipRender;
                    tempRouteItem.desc = routeConfig.desc;
                    tempRouteItem.pathSuffix = routeConfig.pathSuffix
                    if (routeConfig.isSkipRender) {
                        return null;
                    }
                }
                return tempRouteItem
            }).filter(item => item !== null) as RouteItem[];
    }

    /**
     * 延迟加载组件
     */
    private lazyLoadComponent = (key: string) => {
        let TempComponent = React.lazy(() => this.context(key));
        return (
            <Suspense fallback={<LoadingComponent />}>
                <TempComponent title={key} message={this.message} />
            </Suspense>
        );
    }
}
